package it.poli.IA.space;

import it.poli.IA.exceptions.EmptyQueueException;
import it.poli.IA.exceptions.NullActionException;

import java.util.ArrayDeque;
import java.util.Queue;



public class NodeActionMemory extends Node {
	
	private Queue<Action> stillToTryActions;

	private Queue<Action> originallyToTryActions;

	protected NodeActionMemory parentNode;
	
	private NodeActionMemory(State currentState, Node parentNode, Action pastAction, Integer totalCost, Queue<? extends Action> availableActions)
	{
		super(currentState, parentNode, pastAction, totalCost);
		this.stillToTryActions = new ArrayDeque<Action>();
		if (this.parentNode!=null)
		{
			this.originallyToTryActions = this.parentNode.stillToTryActions;
		}
		else
		{
			this.originallyToTryActions = new ArrayDeque<Action>();
			this.originallyToTryActions.addAll(stillToTryActions);
		}
		this.stillToTryActions.addAll(availableActions);
		
	}
	
	public NodeActionMemory(Node node, Queue<? extends Action> availableActions)
	{
		this(node.currentState, node.parentNode, node.pastAction, node.totalCost, availableActions);
		
	}
	
	public NodeActionMemory removeFirstChild() throws EmptyQueueException
	{
		if(this.stillToTryActions.size() > 0)
			return this.generateSon( this.stillToTryActions.remove());
		else
			throw new EmptyQueueException();
	}
	
	private NodeActionMemory generateSon(Action action)
	{
		State stateResult=null;
		try {
			stateResult = this.getCurrentState().getResult(action);
		} catch (CloneNotSupportedException e) {

		}
		Node nodeResult = new Node(stateResult, this, action, this.totalCost + stateResult.cost(action));
		NodeActionMemory node = new  NodeActionMemory(nodeResult, this.getAvailableActionsFrom(stateResult));
		return node;
	
	}
	

	private Queue<? extends Action> getAvailableActionsFrom(State stateResult) {

		Queue<Action> availableActions = new ArrayDeque<Action>();
		for(Action a : this.originallyToTryActions)
		{
			try
			{
				if( this.currentState.isAppliable(a) )
				{
					availableActions.add(a);
				}
			} 
			catch (NullActionException e) {

			}
		}

		return availableActions;
	
	}

	public boolean stillActionToTry()
	{
		if( this.stillToTryActions.size()!= 0)
			return true;
		else return false;
	}
	
	
}
